package com.lightsh.widget;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.RatingBar;
import com.lightsh.flashlight.*;
import com.lightsh.light.Light;

public class VRatingBar extends View{

	private static final String TAG = "VRatingBar";
	private static final boolean DEBUG = true;
	
	private int mCurrentRate;
	private OnRateChangeListener mRateChangeListener;
	private OnTouchDownUpListener mTouchDownUpListener;
	
	protected int mStarsNum = 0;
	protected Drawable mStarsDrawable;
	protected int mDrawableWidth;
	protected int mDrawableHeight;
	protected int mMinRate = 0;
	
	protected boolean mbBottomStart = true;
	
	public VRatingBar(Context context) {
		this(context, null);
	}
	public VRatingBar(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}
	public VRatingBar(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		
		TypedArray a = context.obtainStyledAttributes(attrs,
                R.styleable.VerticalRatingBar);
		mStarsNum = a.getInt(R.styleable.VerticalRatingBar_starsNum, Light.MAX_BRIGHTNESS_LEVEL + 1);
		mStarsDrawable = a.getDrawable(R.styleable.VerticalRatingBar_starsDrawable);
		if(mStarsDrawable == null){
			throw new IllegalArgumentException("must supply a starsDrawable attribute!");
		}
		mDrawableWidth = mStarsDrawable.getIntrinsicWidth();
		mDrawableHeight = mStarsDrawable.getIntrinsicHeight();
		a.recycle();
	}
	
	public void setCurrentRate(int rate){
		if(rate > mStarsNum){
			throw new IllegalArgumentException("rate is bigger than stars number!");
		}
		if(mCurrentRate != rate){
			mCurrentRate = rate;
			notifyRateChange();
			postInvalidate();
		}
	}
	public void setMinRate(int rate){
		if(rate < 0 || rate > mStarsNum){
			throw new IllegalArgumentException("rate cant less than 0 && cant bigger than stars number!");
		}
		mMinRate = rate;
		setCurrentRate(Math.max(mMinRate, mCurrentRate));
	}
	
	public void setOnRateChangeListener(OnRateChangeListener listener){
		mRateChangeListener = listener;
	}
	private void notifyRateChange(){
		if(mRateChangeListener != null){
			mRateChangeListener.onRateChange(this, mCurrentRate);
		}
	}
	public void setOnTouchDownUpListener(OnTouchDownUpListener listener){
		mTouchDownUpListener = listener;
	}
	private void notifyTouchDownUp(boolean bDown){
		if(mTouchDownUpListener != null){
			if(bDown){
				mTouchDownUpListener.onTouchDown(this);
			}else{
				mTouchDownUpListener.onTouchUp(this);
			}
		}
	}
	
	public void setStarsNum(int num){
		if(num <= 0){
			throw new IllegalArgumentException("stars num must > 0");
		}
		mStarsNum = num;
		requestLayout();		
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if(isEnabled()){
			float y = event.getY();
			switch(event.getAction() & MotionEvent.ACTION_MASK){
			case MotionEvent.ACTION_DOWN:
			case MotionEvent.ACTION_CANCEL:
			case MotionEvent.ACTION_MOVE:
			case MotionEvent.ACTION_UP:{
				int currentPos;
				
				if(mbBottomStart){
					int bottom = getPaddingTop() + mDrawableHeight * mStarsNum;
					if(y > bottom){
						currentPos = 0;
					}else{
						currentPos = (int)((bottom - y) / mDrawableHeight) + 1;
					}					
				}else{
					if(y < 0){
						currentPos = 0;
					}else{
						currentPos = (int) (y / mDrawableHeight) + 1;
					}
				}				
				currentPos = Math.max(mMinRate, Math.min(currentPos, mStarsNum));
				setCurrentRate(currentPos);
			}
				break;
			}
			
			if((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_DOWN){
				notifyTouchDownUp(true);
				setPressed(true);
			}else if((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_UP){
				notifyTouchDownUp(false);
				setPressed(false);
			}
			
			return true;
		}
		return false;
	}

	
	private void logTrace(String tip){
		if(DEBUG){
			Log.d(TAG, tip);
		}
	}
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {		
		// 计算出需要实际需要的大小
		int calWidth = mStarsDrawable.getIntrinsicWidth() + getPaddingLeft() + getPaddingRight();
		int calHeight = mStarsDrawable.getIntrinsicHeight() * mStarsNum + getPaddingTop() + getPaddingBottom();		
		int width = resolveSize(Math.max(getSuggestedMinimumWidth(), calWidth), widthMeasureSpec);
		int height = resolveSize(Math.max(getSuggestedMinimumHeight(), calHeight), heightMeasureSpec);
		setMeasuredDimension(width, height);
	}
	@Override
	protected void onDraw(Canvas canvas) {
		int curX = getPaddingLeft();
		int curY = getPaddingTop();		
		for(int i = 0; i < mStarsNum; ++i){
			mStarsDrawable.setBounds(curX, curY, curX + mDrawableWidth, curY + mDrawableHeight);
			boolean bSelect = false;
			if(mbBottomStart){
				if(mStarsNum - mCurrentRate <= i){
					bSelect = true;
				}
			}else{
				if(mCurrentRate > i){
					bSelect = true;
				}
			}
			if(bSelect){
				mStarsDrawable.setState(new int[]{android.R.attr.state_selected});
			}else{
				mStarsDrawable.setState(new int[]{});
			}
			
			mStarsDrawable.draw(canvas);
			curY += mDrawableHeight;
		}
	}
	
	public interface OnRateChangeListener{
		public void onRateChange(VRatingBar ratingBar, int rate);
	}
	public interface OnTouchDownUpListener{
		public void onTouchDown(VRatingBar ratingBar);
		public void onTouchUp(VRatingBar ratingBar);
	}
}
